/******************************************************************************\
    DllMain.cpp is a main module of ACM server plugins.
    Copyright (C) 2008  Victor Vinogradov (fly3333@gmail.com)

    This program is free software: you can redistribute it and/or modify
    it under the terms of the GNU General Public License as published by
    the Free Software Foundation, either version 3 of the License, or
    (at your option) any later version.

    This program is distributed in the hope that it will be useful,
    but WITHOUT ANY WARRANTY; without even the implied warranty of
    MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
    GNU General Public License for more details.

    You should have received a copy of the GNU General Public License
    along with this program.  If not, see <http://www.gnu.org/licenses/>.
\******************************************************************************/

#include <windows.h>
#include ".\Data.h"
#include <Common\StdFile.hpp>
//#include ".\IO.h"
#include <vector>
#include <string>
#include <Common\String.h>
#include <Common\Random.h>
#include <ctime>
#include <Common\CriticalSection.hpp>
#include <Common\Log.h>
#include <Auxiliary.h>
using namespace std;

cLog Log;

HMODULE CurrentModule;

__declspec( dllexport ) bool __stdcall MainProc( int command, unsigned long idata, void *pdata )
{
	switch( command )
	{
	case SET_PROXY_PORT:
		return SetProxyPort( ( unsigned short )idata );
	case GET_TITLE_LENGTH:
		return GetTitleLength( ( unsigned long * )pdata );
	case GET_TITLE:
		return GetTitle( ( char * )pdata );
	case GET_COMMENT_LENGTH:
		return GetCommentLength( ( unsigned long * )pdata );
	case GET_COMMENT:
		return GetComment( ( char * )pdata );
	case GET_VARIABLES_COUNT:
		return GetVariablesCount( ( unsigned long * )pdata );
	//case GET_VARIABLE_NAME_LENGTH:
	//	return GetVariableNameLength( idata, ( unsigned long * )pdata );
	//case GET_VARIABLE_NAME:
	//	return GetVariableName( idata, ( char * )pdata );
	case SET_VARIABLE_VALUE:
		return SetVariableValue( idata, ( char * )pdata );
	case GET_PROBLEMS_COUNT:
		return GetProblemsCount( ( unsigned long * )pdata );
	case GET_PROBLEMS_IDS:
		return GetProblemsIds( ( unsigned long * )pdata );
	case GET_PROBLEM_HEADER_LENGTH:
		return GetProblemHeaderLength( idata, ( unsigned long * )pdata );
	case GET_PROBLEM_HEADER:
		return GetProblemHeader( idata, ( char * )pdata );
	case GET_PROBLEM_BODY_LENGTH:
		return GetProblemBodyLength( idata, ( unsigned long * )pdata );
	case GET_PROBLEM_BODY:
		return GetProblemBody( idata, ( char * )pdata );
	case GET_PROBLEM_ADDITIONS_COUNT:
		return GetProblemAdditionsCount( idata, ( unsigned long * )pdata );
	case GET_PROBLEM_ADDITIONS_IDS:
		return GetProblemAdditionsIds( idata, ( unsigned long * )pdata );
	case GET_ADDITION_NAME_LENGTH:
		return GetAdditionNameLength( idata, ( unsigned long * )pdata );
	case GET_ADDITION_NAME:
		return GetAdditionName( idata, ( char * )pdata );
	case GET_ADDITION_DATA_LENGTH:
		return GetAdditionDataLength( idata, ( unsigned long * )pdata );
	case GET_ADDITION_DATA:
		return GetAdditionData( idata, ( char * )pdata );
	case GET_LANGUAGES_COUNT:
		return GetLanguagesCount( ( unsigned long * )pdata );
	case GET_LANGUAGES_IDS:
		return GetLanguagesIds( ( unsigned long * )pdata );
	case GET_LANGUAGE_TITLE_LENGTH:
		return GetLanguageTitleLength( idata, ( unsigned long * )pdata );
	case GET_LANGUAGE_TITLE:
		return GetLanguageTitle( idata, ( char * )pdata );
	case SUBMIT:
		return Submit( ( sSubmit * )pdata );
	case GET_LAST_COMPILATION_ERROR_LENGTH:
		return GetLastCompilationErrorLength( ( unsigned long * )pdata );
	case GET_LAST_COMPILATION_ERROR:
		return GetLastCompilationError( ( char * )pdata );
	case GET_VARIABLE_PROPERTIES_LENGTH:
		return GetVariablePropertiesLength( idata, ( unsigned long * )pdata );
	case GET_VARIABLE_PROPERTIES:
		return GetVariableProperties( idata, ( char * )pdata );
	default:
		return false;
	}
}

bool _stdcall DllMain( HANDLE handle, DWORD reason, LPVOID )
{
	static const size_t MAX_FILE_NAME = 256;
	char file_name[ MAX_FILE_NAME + 1 ];
	switch( reason )
	{
	case DLL_PROCESS_ATTACH:
		StartRandom( ( unsigned )time( NULL ) );
		CurrentModule = ( HMODULE )handle;
		if( GetModuleFileName( ( HMODULE )handle, file_name, MAX_FILE_NAME ) != 0 )
		{
			vector< string > path = Split( file_name, "\\" );
			vector< string > name = Split( path.back(), "." );
			name.back() = "log";
			path.back() = Concat( name, "." );
			Log.Create( Concat( path, "\\" ).c_str(), "at" );
			Log.Notice( "%s attached.\n", path.back().c_str() );
			Log.Notice( "Plugin title: %s\n", Title );
		}
		break;
	case DLL_PROCESS_DETACH:
		if( GetModuleFileName( ( HMODULE )handle, file_name, MAX_FILE_NAME ) != 0 )
		{
			vector< string > path = Split( file_name, "\\" );
			vector< string > name = Split( path.back(), "." );
			name.back() = "log";
			path.back() = Concat( name, "." );
			Log.Notice( "%s detached.\n", path.back().c_str() );
		}
		break;
	case DLL_THREAD_ATTACH:
		break;
	case DLL_THREAD_DETACH:
		break;
	}
	return true;
}
